今天接續使用es,來試試多次book事件的commit是不是都可以正確的作用。
第一個指令:建立書籍檔案
let store = mem_store::MemStore::<Book>::default();
let book_id = String::from("test-book-id");
let mut aggregate = store
.load_aggregate(&book_id)
.await
.unwrap();
let command = BookCommand::CreateBook {
id: book_id.to_string(),
title: "test-book-title".to_string(),
isbn10: "1234567890".to_string(),
description: "test-book-description".to_string(),
};
let events = aggregate.aggregate.handle(command).await.unwrap();
store.commit(events, aggregate, Default::default()).await.unwrap();
println!("\n=== create 後的 es ===\n{:#?}", store);
store內容
=== create 後的 es ===
MemStore {
events: RwLock {
data: {
"test-book-id": [
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 1,
payload: BookCreated {
id: "test-book-id",
title: "test-book-title",
isbn10: "1234567890",
description: "test-book-description",
},
metadata: {},
},
],
},
poisoned: false,
..
},
}
book aggregate:
=== create 後的 aggregate ===
MemStoreAggregateContext {
aggregate_id: "test-book-id",
aggregate: Book {
id: "test-book-id",
title: "test-book-title",
isbn10: "1234567890",
description: "test-book-description",
copies: 0,
lending_records: [],
lent_history: [],
},
current_sequence: 1,
}
書籍入庫指令:
let command = BookCommand::IngestBook {
id: "test-book-id".to_string(),
copies: 3,
};
let events = aggregate.aggregate.handle(command).await.unwrap();
store.commit(events, aggregate, Default::default()).await.unwrap();
println!("\n=== ingest 後的 es ===\n{:#?}", store);
入庫後的 es:
data: {
"test-book-id": [
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 1,
payload: BookCreated {
id: "test-book-id",
title: "test-book-title",
isbn10: "1234567890",
description: "test-book-description",
},
metadata: {},
},
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 2,
payload: BookIngested {
id: "test-book-id",
copies: 3,
},
metadata: {},
},
],
},
入庫後的 aggregate
MemStoreAggregateContext {
aggregate_id: "test-book-id",
aggregate: Book {
id: "test-book-id",
title: "test-book-title",
isbn10: "1234567890",
description: "test-book-description",
copies: 3,
lending_records: [],
lent_history: [],
},
current_sequence: 2,
}
借閱指令
let command = BookCommand::LendBook(
LendingRecord {
reader_id: "test-reader-id".to_string(),
lent_date: Utc::now(),
due_date: Utc::now().add(chrono::Duration::days(7)),
});
let events = aggregate.aggregate.handle(command).await.unwrap();
store.commit(events, aggregate, Default::default()).await.unwrap();
println!("\n=== lend 後的 es ===\n{:#?}", store);
借閱後 es
data: {
"test-book-id": [
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 1,
payload: BookCreated {
id: "test-book-id",
title: "test-book-title",
isbn10: "1234567890",
description: "test-book-description",
},
},
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 2,
payload: BookIngested {
id: "test-book-id",
copies: 3,
},
},
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 3,
payload: BookLent(
LendingRecord {
reader_id: "test-reader-id",
lent_date: 2023-09-22T13:13:26.980063588Z,
due_date: 2023-09-29T13:13:26.980065730Z,
},
),
},
],
},
借閱後aggregate
MemStoreAggregateContext {
aggregate_id: "test-book-id",
aggregate: Book {
id: "test-book-id",
title: "test-book-title",
isbn10: "1234567890",
description: "test-book-description",
copies: 3,
lending_records: [
LendingRecord {
reader_id: "test-reader-id",
lent_date: 2023-09-22T13:13:26.980063588Z,
due_date: 2023-09-29T13:13:26.980065730Z,
},
],
lent_history: [],
},
current_sequence: 3,
}
歸還指令
let command = BookCommand::ReturnBook(
LentRecord {
reader_id: "test-reader-id".to_string(),
lent_date: Utc::now(),
due_date: Utc::now().add(chrono::Duration::days(7)),
returned_date: Some(Utc::now()),
});
let events = aggregate.aggregate.handle(command).await.unwrap();
store.commit(events, aggregate, Default::default()).await.unwrap();
println!("\n=== return 後的 es ===\n{:#?}", store);
歸還後 store
data: {
"test-book-id": [
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 1,
payload: BookCreated {
id: "test-book-id",
title: "test-book-title",
isbn10: "1234567890",
description: "test-book-description",
},
metadata: {},
},
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 2,
payload: BookIngested {
id: "test-book-id",
copies: 3,
},
metadata: {},
},
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 3,
payload: BookLent(
LendingRecord {
reader_id: "test-reader-id",
lent_date: 2023-09-22T13:30:51.377688412Z,
due_date: 2023-09-29T13:30:51.377691261Z,
},
),
metadata: {},
},
EventEnvelope {
aggregate_id: "test-book-id",
sequence: 4,
payload: BookReturned(
LentRecord {
reader_id: "test-reader-id",
lent_date: 2023-09-22T13:30:51.377878940Z,
due_date: 2023-09-29T13:30:51.377879745Z,
returned_date: Some(
2023-09-22T13:30:51.377880700Z,
),
},
),
metadata: {},
},
],
},
歸還後 aggregate
MemStoreAggregateContext {
aggregate_id: "test-book-id",
aggregate: Book {
id: "test-book-id",
title: "test-book-title",
isbn10: "1234567890",
description: "test-book-description",
copies: 3,
lending_records: [],
lent_history: [
LentRecord {
reader_id: "test-reader-id",
lent_date: 2023-09-22T13:30:51.377878940Z,
due_date: 2023-09-29T13:30:51.377879745Z,
returned_date: Some(
2023-09-22T13:30:51.377880700Z,
),
},
],
},
current_sequence: 4,
}
可以看到存放event store裡用 event envelop存放事件本身資料,以及事件的meta資訊,而從store讀取aggregate時,會依每個事件套用,並顯示aggregate目前版次current_sequence
。